home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / zoneinfo / src / zic.c < prev   
Encoding:
C/C++ Source or Header  |  1995-08-28  |  45.2 KB  |  1,932 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Arthur David Olson of the National Cancer Institute.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)zic.c    5.3 (Berkeley) 4/20/91";
  39. #endif /* not lint */
  40.  
  41. #ifdef notdef
  42. static char    elsieid[] = "@(#)zic.c    4.12";
  43. #endif
  44.  
  45. #include <sys/types.h>
  46. #include <sys/cdefs.h>
  47. #include <sys/stat.h>
  48. #include <time.h>
  49. #include <tzfile.h>
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #include <string.h>
  53. #include <stdlib.h>
  54.  
  55. FILE *
  56. dj_fopen(const char *fn, char *mode)
  57. {
  58.   char *cp;
  59.   FILE *f;
  60.   char *fn2 = (char *)alloca(strlen(fn)+1);
  61.   strcpy(fn2, fn);
  62.   for (cp=fn2; *cp; cp++)
  63.     if (*cp == '+')
  64.       *cp = '%';
  65.   f = fopen(fn2, mode);
  66.   return f;
  67. }
  68. #define fopen dj_fopen
  69.  
  70. int dj_link(char *from, char *to)
  71. {
  72.   FILE *f, *t;
  73.   char buf[4096];
  74.   int b;
  75.   f = fopen(from, "rb");
  76.   if (f == 0)
  77.     return -1;
  78.   t = fopen(to, "wb");
  79.   if (t == 0)
  80.   {
  81.     fclose(f);
  82.     return -1;
  83.   }
  84.   while ((b=fread(buf, 1, 4096, f))>0)
  85.     fwrite(buf, 1, b, t);
  86.   fclose(f);
  87.   fclose(t);
  88.   return 0;
  89. }
  90. #define link dj_link
  91.  
  92. #ifndef TRUE
  93. #define TRUE    1
  94. #define FALSE    0
  95. #endif /* !defined TRUE */
  96.  
  97. struct rule {
  98.     const char *    r_filename;
  99.     int        r_linenum;
  100.     const char *    r_name;
  101.  
  102.     int        r_loyear;    /* for example, 1986 */
  103.     int        r_hiyear;    /* for example, 1986 */
  104.     const char *    r_yrtype;
  105.  
  106.     int        r_month;    /* 0..11 */
  107.  
  108.     int        r_dycode;    /* see below */
  109.     int        r_dayofmonth;
  110.     int        r_wday;
  111.  
  112.     long        r_tod;        /* time from midnight */
  113.     int        r_todisstd;    /* above is standard time if TRUE */
  114.                     /* or wall clock time if FALSE */
  115.     long        r_stdoff;    /* offset from standard time */
  116.     const char *    r_abbrvar;    /* variable part of abbreviation */
  117.  
  118.     int        r_todo;        /* a rule to do (used in outzone) */
  119.     time_t        r_temp;        /* used in outzone */
  120. };
  121.  
  122. /*
  123. **    r_dycode        r_dayofmonth    r_wday
  124. */
  125.  
  126. #define DC_DOM        0    /* 1..31 */    /* unused */
  127. #define DC_DOWGEQ    1    /* 1..31 */    /* 0..6 (Sun..Sat) */
  128. #define DC_DOWLEQ    2    /* 1..31 */    /* 0..6 (Sun..Sat) */
  129.  
  130. struct zone {
  131.     const char *    z_filename;
  132.     int        z_linenum;
  133.  
  134.     const char *    z_name;
  135.     long        z_gmtoff;
  136.     const char *    z_rule;
  137.     const char *    z_format;
  138.  
  139.     long        z_stdoff;
  140.  
  141.     struct rule *    z_rules;
  142.     int        z_nrules;
  143.  
  144.     struct rule    z_untilrule;
  145.     time_t        z_untiltime;
  146. };
  147.  
  148. extern char *    icatalloc __P((char * old, const char * new));
  149. extern char *    icpyalloc __P((const char * string));
  150. extern void    ifree __P((char * p));
  151. extern char *    imalloc __P((int n));
  152. extern char *    irealloc __P((char * old, int n));
  153. /* extern int    link __P((const char * fromname, const char * toname));*/
  154. extern char *    optarg;
  155. extern int    optind;
  156. extern void    perror __P((const char * string));
  157. extern char *    scheck __P((const char * string, const char * format));
  158. static void    addtt __P((time_t starttime, int type));
  159. static int    addtype
  160.             __P((long gmtoff, const char * abbr, int isdst,
  161.             int ttisstd));
  162. static void    addleap __P((time_t t, int positive, int rolling));
  163. static void    adjleap __P((void));
  164. static void    associate __P((void));
  165. static int    ciequal __P((const char * ap, const char * bp));
  166. static void    convert __P((long val, char * buf));
  167. static void    dolink __P((const char * fromfile, const char * tofile));
  168. static void    eat __P((const char * name, int num));
  169. static void    eats __P((const char * name, int num,
  170.             const char * rname, int rnum));
  171. static long    eitol __P((int i));
  172. static void    error __P((const char * message));
  173. static char **    getfields __P((char * buf));
  174. static long    gethms __P((char * string, const char * errstrng,
  175.             int signable));
  176. static void    infile __P((const char * filename));
  177. static void    inleap __P((char ** fields, int nfields));
  178. static void    inlink __P((char ** fields, int nfields));
  179. static void    inrule __P((char ** fields, int nfields));
  180. static int    inzcont __P((char ** fields, int nfields));
  181. static int    inzone __P((char ** fields, int nfields));
  182. static int    inzsub __P((char ** fields, int nfields, int iscont));
  183. static int    itsabbr __P((const char * abbr, const char * word));
  184. static int    itsdir __P((const char * name));
  185. static int    lowerit __P((int c));
  186. static char *    memcheck __P((char * tocheck));
  187. static int    mkdirs __P((char * filename));
  188. static void    newabbr __P((const char * abbr));
  189. static long    oadd __P((long t1, long t2));
  190. static void    outzone __P((const struct zone * zp, int ntzones));
  191. static void    puttzcode __P((long code, FILE * fp));
  192. static int    rcomp __P((const void *leftp, const void *rightp));
  193. static time_t    rpytime __P((const struct rule * rp, int wantedy));
  194. static void    rulesub __P((struct rule * rp, char * loyearp, char * hiyearp,
  195.         char * typep, char * monthp, char * dayp, char * timep));
  196. static void    setboundaries __P((void));
  197. static time_t    tadd __P((time_t t1, long t2));
  198. static void    usage __P((void));
  199. static void    writezone __P((const char * name));
  200. static int    yearistype __P((int year, const char * type));
  201.  
  202. static int        charcnt;
  203. static int        errors;
  204. static const char *    filename;
  205. static int        leapcnt;
  206. static int        linenum;
  207. static time_t        max_time;
  208. static int        max_year;
  209. static time_t        min_time;
  210. static int        min_year;
  211. static int        noise;
  212. static const char *    rfilename;
  213. static int        rlinenum;
  214. static const char *    progname;
  215. static int        timecnt;
  216. static int        typecnt;
  217. static int        tt_signed;
  218.  
  219. /*
  220. ** Line codes.
  221. */
  222.  
  223. #define LC_RULE        0
  224. #define LC_ZONE        1
  225. #define LC_LINK        2
  226. #define LC_LEAP        3
  227.  
  228. /*
  229. ** Which fields are which on a Zone line.
  230. */
  231.  
  232. #define ZF_NAME        1
  233. #define ZF_GMTOFF    2
  234. #define ZF_RULE        3
  235. #define ZF_FORMAT    4
  236. #define ZF_TILYEAR    5
  237. #define ZF_TILMONTH    6
  238. #define ZF_TILDAY    7
  239. #define ZF_TILTIME    8
  240. #define ZONE_MINFIELDS    5
  241. #define ZONE_MAXFIELDS    9
  242.  
  243. /*
  244. ** Which fields are which on a Zone continuation line.
  245. */
  246.  
  247. #define ZFC_GMTOFF    0
  248. #define ZFC_RULE    1
  249. #define ZFC_FORMAT    2
  250. #define ZFC_TILYEAR    3
  251. #define ZFC_TILMONTH    4
  252. #define ZFC_TILDAY    5
  253. #define ZFC_TILTIME    6
  254. #define ZONEC_MINFIELDS    3
  255. #define ZONEC_MAXFIELDS    7
  256.  
  257. /*
  258. ** Which files are which on a Rule line.
  259. */
  260.  
  261. #define RF_NAME        1
  262. #define RF_LOYEAR    2
  263. #define RF_HIYEAR    3
  264. #define RF_COMMAND    4
  265. #define RF_MONTH    5
  266. #define RF_DAY        6
  267. #define RF_TOD        7
  268. #define RF_STDOFF    8
  269. #define RF_ABBRVAR    9
  270. #define RULE_FIELDS    10
  271.  
  272. /*
  273. ** Which fields are which on a Link line.
  274. */
  275.  
  276. #define LF_FROM        1
  277. #define LF_TO        2
  278. #define LINK_FIELDS    3
  279.  
  280. /*
  281. ** Which fields are which on a Leap line.
  282. */
  283.  
  284. #define LP_YEAR        1
  285. #define LP_MONTH    2
  286. #define LP_DAY        3
  287. #define LP_TIME        4
  288. #define LP_CORR        5
  289. #define LP_ROLL        6
  290. #define LEAP_FIELDS    7
  291.  
  292. /*
  293. ** Year synonyms.
  294. */
  295.  
  296. #define YR_MINIMUM    0
  297. #define YR_MAXIMUM    1
  298. #define YR_ONLY        2
  299.  
  300. static struct rule *    rules;
  301. static int        nrules;    /* number of rules */
  302.  
  303. static struct zone *    zones;
  304. static int        nzones;    /* number of zones */
  305.  
  306. struct link {
  307.     const char *    l_filename;
  308.     int        l_linenum;
  309.     const char *    l_from;
  310.     const char *    l_to;
  311. };
  312.  
  313. static struct link *    links;
  314. static int        nlinks;
  315.  
  316. struct lookup {
  317.     const char *    l_word;
  318.     const int    l_value;
  319. };
  320.  
  321. static struct lookup const *    byword __P((const char * string,
  322.                     const struct lookup * lp));
  323.  
  324. static struct lookup const    line_codes[] = {
  325.     "Rule",        LC_RULE,
  326.     "Zone",        LC_ZONE,
  327.     "Link",        LC_LINK,
  328.     "Leap",        LC_LEAP,
  329.     NULL,        0
  330. };
  331.  
  332. static struct lookup const    mon_names[] = {
  333.     "January",    TM_JANUARY,
  334.     "February",    TM_FEBRUARY,
  335.     "March",    TM_MARCH,
  336.     "April",    TM_APRIL,
  337.     "May",        TM_MAY,
  338.     "June",        TM_JUNE,
  339.     "July",        TM_JULY,
  340.     "August",    TM_AUGUST,
  341.     "September",    TM_SEPTEMBER,
  342.     "October",    TM_OCTOBER,
  343.     "November",    TM_NOVEMBER,
  344.     "December",    TM_DECEMBER,
  345.     NULL,        0
  346. };
  347.  
  348. static struct lookup const    wday_names[] = {
  349.     "Sunday",    TM_SUNDAY,
  350.     "Monday",    TM_MONDAY,
  351.     "Tuesday",    TM_TUESDAY,
  352.     "Wednesday",    TM_WEDNESDAY,
  353.     "Thursday",    TM_THURSDAY,
  354.     "Friday",    TM_FRIDAY,
  355.     "Saturday",    TM_SATURDAY,
  356.     NULL,        0
  357. };
  358.  
  359. static struct lookup const    lasts[] = {
  360.     "last-Sunday",        TM_SUNDAY,
  361.     "last-Monday",        TM_MONDAY,
  362.     "last-Tuesday",        TM_TUESDAY,
  363.     "last-Wednesday",    TM_WEDNESDAY,
  364.     "last-Thursday",    TM_THURSDAY,
  365.     "last-Friday",        TM_FRIDAY,
  366.     "last-Saturday",    TM_SATURDAY,
  367.     NULL,            0
  368. };
  369.  
  370. static struct lookup const    begin_years[] = {
  371.     "minimum",        YR_MINIMUM,
  372.     "maximum",        YR_MAXIMUM,
  373.     NULL,            0
  374. };
  375.  
  376. static struct lookup const    end_years[] = {
  377.     "minimum",        YR_MINIMUM,
  378.     "maximum",        YR_MAXIMUM,
  379.     "only",            YR_ONLY,
  380.     NULL,            0
  381. };
  382.  
  383. static struct lookup const    leap_types[] = {
  384.     "Rolling",        TRUE,
  385.     "Stationary",        FALSE,
  386.     NULL,            0
  387. };
  388.  
  389. static const int    len_months[2][MONSPERYEAR] = {
  390.     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
  391.     31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  392. };
  393.  
  394. static const int    len_years[2] = {
  395.     DAYSPERNYEAR, DAYSPERLYEAR
  396. };
  397.  
  398. static time_t        ats[TZ_MAX_TIMES];
  399. static unsigned char    types[TZ_MAX_TIMES];
  400. static long        gmtoffs[TZ_MAX_TYPES];
  401. static char        isdsts[TZ_MAX_TYPES];
  402. static char        abbrinds[TZ_MAX_TYPES];
  403. static char        ttisstds[TZ_MAX_TYPES];
  404. static char        chars[TZ_MAX_CHARS];
  405. static time_t        trans[TZ_MAX_LEAPS];
  406. static long        corr[TZ_MAX_LEAPS];
  407. static char        roll[TZ_MAX_LEAPS];
  408.  
  409. /*
  410. ** Memory allocation.
  411. */
  412.  
  413. static char *
  414. memcheck(ptr)
  415. char * const    ptr;
  416. {
  417.     if (ptr == NULL) {
  418.         (void) perror(progname);
  419.         (void) exit(EXIT_FAILURE);
  420.     }
  421.     return ptr;
  422. }
  423.  
  424. #define emalloc(size)        memcheck(imalloc(size))
  425. #define erealloc(ptr, size)    memcheck(irealloc(ptr, size))
  426. #define ecpyalloc(ptr)        memcheck(icpyalloc(ptr))
  427. #define ecatalloc(oldp, newp)    memcheck(icatalloc(oldp, newp))
  428.  
  429. /*
  430. ** Error handling.
  431. */
  432.  
  433. static void
  434. eats(name, num, rname, rnum)
  435. const char * const    name;
  436. const int        num;
  437. const char * const    rname;
  438. const int        rnum;
  439. {
  440.     filename = name;
  441.     linenum = num;
  442.     rfilename = rname;
  443.     rlinenum = rnum;
  444. }
  445.  
  446. static void
  447. eat(name, num)
  448. const char * const    name;
  449. const int        num;
  450. {
  451.     eats(name, num, (char *) NULL, -1);
  452. }
  453.  
  454. static void
  455. error(string)
  456. const char * const    string;
  457. {
  458.     /*
  459.     ** Match the format of "cc" to allow sh users to
  460.     **     zic ... 2>&1 | error -t "*" -v
  461.     ** on BSD systems.
  462.     */
  463.     (void) fprintf(stderr, "\"%s\", line %d: %s",
  464.         filename, linenum, string);
  465.     if (rfilename != NULL)
  466.         (void) fprintf(stderr, " (rule from \"%s\", line %d)",
  467.             rfilename, rlinenum);
  468.     (void) fprintf(stderr, "\n");
  469.     ++errors;
  470. }
  471.  
  472. static void
  473. usage()
  474. {
  475.     (void) fprintf(stderr,
  476. "%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\
  477. \t[ -L leapseconds ] [ filename ... ]\n",
  478.         progname, progname);
  479.     (void) exit(EXIT_FAILURE);
  480. }
  481.  
  482. static const char *    psxrules = NULL;
  483. static const char *    lcltime = NULL;
  484. static const char *    directory = NULL;
  485. static const char *    leapsec = NULL;
  486. static int        sflag = FALSE;
  487.  
  488. int
  489. main(argc, argv)
  490. int    argc;
  491. char *    argv[];
  492. {
  493.     register int    i, j;
  494.     register int    c;
  495.  
  496.     (void) umask(umask(022) | 022);
  497.     progname = argv[0];
  498.     while ((c = getopt(argc, argv, "d:l:p:L:vs")) != EOF)
  499.         switch (c) {
  500.             default:
  501.                 usage();
  502.             case 'd':
  503.                 if (directory == NULL)
  504.                     directory = optarg;
  505.                 else {
  506.                     (void) fprintf(stderr,
  507. "%s: More than one -d option specified\n",
  508.                         progname);
  509.                     (void) exit(EXIT_FAILURE);
  510.                 }
  511.                 break;
  512.             case 'l':
  513.                 if (lcltime == NULL)
  514.                     lcltime = optarg;
  515.                 else {
  516.                     (void) fprintf(stderr,
  517. "%s: More than one -l option specified\n",
  518.                         progname);
  519.                     (void) exit(EXIT_FAILURE);
  520.                 }
  521.                 break;
  522.             case 'p':
  523.                 if (psxrules == NULL)
  524.                     psxrules = optarg;
  525.                 else {
  526.                     (void) fprintf(stderr,
  527. "%s: More than one -p option specified\n",
  528.                         progname);
  529.                     (void) exit(EXIT_FAILURE);
  530.                 }
  531.                 break;
  532.             case 'L':
  533.                 if (leapsec == NULL)
  534.                     leapsec = optarg;
  535.                 else {
  536.                     (void) fprintf(stderr,
  537. "%s: More than one -L option specified\n",
  538.                         progname);
  539.                     (void) exit(EXIT_FAILURE);
  540.                 }
  541.                 break;
  542.             case 'v':
  543.                 noise = TRUE;
  544.                 break;
  545.             case 's':
  546.                 sflag = TRUE;
  547.                 break;
  548.         }
  549.     if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
  550.         usage();    /* usage message by request */
  551.     if (directory == NULL)
  552.         directory = TZDIR;
  553.  
  554.     setboundaries();
  555.  
  556.     if (optind < argc && leapsec != NULL) {
  557.         infile(leapsec);
  558.         adjleap();
  559.     }
  560.  
  561.     zones = (struct zone *) emalloc(0);
  562.     rules = (struct rule *) emalloc(0);
  563.     links = (struct link *) emalloc(0);
  564.     for (i = optind; i < argc; ++i)
  565.         infile(argv[i]);
  566.     if (errors)
  567.         (void) exit(EXIT_FAILURE);
  568.     associate();
  569.     for (i = 0; i < nzones; i = j) {
  570.         /*
  571.         ** Find the next non-continuation zone entry.
  572.         */
  573.         for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
  574.             ;
  575.         outzone(&zones[i], j - i);
  576.     }
  577.     /*
  578.     ** Make links.
  579.     */
  580.     for (i = 0; i < nlinks; ++i)
  581.         dolink(links[i].l_from, links[i].l_to);
  582.     if (lcltime != NULL)
  583.         dolink(lcltime, TZDEFAULT);
  584.     if (psxrules != NULL)
  585.         dolink(psxrules, TZDEFRULES);
  586.     return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
  587. }
  588.  
  589. static void
  590. dolink(fromfile, tofile)
  591. const char * const    fromfile;
  592. const char * const    tofile;
  593. {
  594.     register char *    fromname;
  595.     register char *    toname;
  596.  
  597.     fromname = ecpyalloc(directory);
  598.     fromname = ecatalloc(fromname, "/");
  599.     fromname = ecatalloc(fromname, fromfile);
  600.     toname = ecpyalloc(directory);
  601.     toname = ecatalloc(toname, "/");
  602.     toname = ecatalloc(toname, tofile);
  603.     /*
  604.     ** We get to be careful here since
  605.     ** there's a fair chance of root running us.
  606.     */
  607.     if (!itsdir(toname))
  608.         (void) remove(toname);
  609.     if (link(fromname, toname) != 0) {
  610.         (void) fprintf(stderr, "%s: Can't link from %s to ",
  611.             progname, fromname);
  612.         (void) perror(toname);
  613.         (void) exit(EXIT_FAILURE);
  614.     }
  615.     ifree(fromname);
  616.     ifree(toname);
  617. }
  618.  
  619. static void
  620. setboundaries()
  621. {
  622.     register time_t    bit;
  623.  
  624.     for (bit = 1; bit > 0; bit <<= 1)
  625.         ;
  626.     if (bit == 0) {        /* time_t is an unsigned type */
  627.         tt_signed = FALSE;
  628.         min_time = 0;
  629.         max_time = ~(time_t) 0;
  630.         if (sflag)
  631.             max_time >>= 1;
  632.     } else {
  633.         tt_signed = TRUE;
  634.         min_time = bit;
  635.         max_time = bit;
  636.         ++max_time;
  637.         max_time = -max_time;
  638.         if (sflag)
  639.             min_time = 0;
  640.     }
  641.     min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
  642.     max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
  643. }
  644.  
  645. static int
  646. itsdir(name)
  647. const char * const    name;
  648. {
  649.     struct stat    s;
  650.  
  651.     return (stat(name, &s) == 0 && S_ISDIR(s.st_mode));
  652. }
  653.  
  654. /*
  655. ** Associate sets of rules with zones.
  656. */
  657.  
  658. /*
  659. ** Sort by rule name.
  660. */
  661.  
  662. static int
  663. rcomp(cp1, cp2)
  664. const void *    cp1;
  665. const void *    cp2;
  666. {
  667.     return strcmp(((struct rule *) cp1)->r_name,
  668.         ((struct rule *) cp2)->r_name);
  669. }
  670.  
  671. static void
  672. associate()
  673. {
  674.     register struct zone *    zp;
  675.     register struct rule *    rp;
  676.     register int        base, out;
  677.     register int        i;
  678.  
  679.     if (nrules != 0)
  680.         (void) qsort((void *) rules, (size_t) nrules,
  681.              (size_t) sizeof *rules, rcomp);
  682.     for (i = 0; i < nzones; ++i) {
  683.         zp = &zones[i];
  684.         zp->z_rules = NULL;
  685.         zp->z_nrules = 0;
  686.     }
  687.     for (base = 0; base < nrules; base = out) {
  688.         rp = &rules[base];
  689.         for (out = base + 1; out < nrules; ++out)
  690.             if (strcmp(rp->r_name, rules[out].r_name) != 0)
  691.                 break;
  692.         for (i = 0; i < nzones; ++i) {
  693.             zp = &zones[i];
  694.             if (strcmp(zp->z_rule, rp->r_name) != 0)
  695.                 continue;
  696.             zp->z_rules = rp;
  697.             zp->z_nrules = out - base;
  698.         }
  699.     }
  700.     for (i = 0; i < nzones; ++i) {
  701.         zp = &zones[i];
  702.         if (zp->z_nrules == 0) {
  703.             /*
  704.             ** Maybe we have a local standard time offset.
  705.             */
  706.             eat(zp->z_filename, zp->z_linenum);
  707.             zp->z_stdoff =
  708.                 gethms((char *)zp->z_rule, "unruly zone", TRUE);
  709.             /*
  710.             ** Note, though, that if there's no rule,
  711.             ** a '%s' in the format is a bad thing.
  712.             */
  713.             if (strchr(zp->z_format, '%') != 0)
  714.                 error("%s in ruleless zone");
  715.         }
  716.     }
  717.     if (errors)
  718.         (void) exit(EXIT_FAILURE);
  719. }
  720.  
  721. static void
  722. infile(name)
  723. const char *    name;
  724. {
  725.     register FILE *            fp;
  726.     register char **        fields;
  727.     register char *            cp;
  728.     register const struct lookup *    lp;
  729.     register int            nfields;
  730.     register int            wantcont;
  731.     register int            num;
  732.     char                buf[BUFSIZ];
  733.  
  734.     if (strcmp(name, "-") == 0) {
  735.         name = "standard input";
  736.         fp = stdin;
  737.     } else if ((fp = fopen(name, "r")) == NULL) {
  738.         (void) fprintf(stderr, "%s: Can't open ", progname);
  739.         (void) perror(name);
  740.         (void) exit(EXIT_FAILURE);
  741.     }
  742.     wantcont = FALSE;
  743.     for (num = 1; ; ++num) {
  744.         eat(name, num);
  745.         if (fgets(buf, (int) sizeof buf, fp) != buf)
  746.             break;
  747.         cp = strchr(buf, '\n');
  748.         if (cp == NULL) {
  749.             error("line too long");
  750.             (void) exit(EXIT_FAILURE);
  751.         }
  752.         *cp = '\0';
  753.         fields = getfields(buf);
  754.         nfields = 0;
  755.         while (fields[nfields] != NULL) {
  756.             if (ciequal(fields[nfields], "-"))
  757.                 fields[nfields] = "";
  758.             ++nfields;
  759.         }
  760.         if (nfields == 0) {
  761.             /* nothing to do */
  762.         } else if (wantcont) {
  763.             wantcont = inzcont(fields, nfields);
  764.         } else {
  765.             lp = byword(fields[0], line_codes);
  766.             if (lp == NULL)
  767.                 error("input line of unknown type");
  768.             else switch ((int) (lp->l_value)) {
  769.                 case LC_RULE:
  770.                     inrule(fields, nfields);
  771.                     wantcont = FALSE;
  772.                     break;
  773.                 case LC_ZONE:
  774.                     wantcont = inzone(fields, nfields);
  775.                     break;
  776.                 case LC_LINK:
  777.                     inlink(fields, nfields);
  778.                     wantcont = FALSE;
  779.                     break;
  780.                 case LC_LEAP:
  781.                     if (name != leapsec)
  782.                         (void) fprintf(stderr,
  783. "%s: Leap line in non leap seconds file %s\n",
  784.                             progname, name);
  785.                     else    inleap(fields, nfields);
  786.                     wantcont = FALSE;
  787.                     break;
  788.                 default:    /* "cannot happen" */
  789.                     (void) fprintf(stderr,
  790. "%s: panic: Invalid l_value %d\n",
  791.                         progname, lp->l_value);
  792.                     (void) exit(EXIT_FAILURE);
  793.             }
  794.         }
  795.         ifree((char *) fields);
  796.     }
  797.     if (ferror(fp)) {
  798.         (void) fprintf(stderr, "%s: Error reading ", progname);
  799.         (void) perror(filename);
  800.         (void) exit(EXIT_FAILURE);
  801.     }
  802.     if (fp != stdin && fclose(fp)) {
  803.         (void) fprintf(stderr, "%s: Error closing ", progname);
  804.         (void) perror(filename);
  805.         (void) exit(EXIT_FAILURE);
  806.     }
  807.     if (wantcont)
  808.         error("expected continuation line not found");
  809. }
  810.  
  811. /*
  812. ** Convert a string of one of the forms
  813. **    h    -h     hh:mm    -hh:mm    hh:mm:ss    -hh:mm:ss
  814. ** into a number of seconds.
  815. ** A null string maps to zero.
  816. ** Call error with errstring and return zero on errors.
  817. */
  818.  
  819. static long
  820. gethms(string, errstring, signable)
  821. char *        string;
  822. const char * const    errstring;
  823. const int        signable;
  824. {
  825.     int    hh, mm, ss, sign;
  826.  
  827.     if (string == NULL || *string == '\0')
  828.         return 0;
  829.     if (!signable)
  830.         sign = 1;
  831.     else if (*string == '-') {
  832.         sign = -1;
  833.         ++string;
  834.     } else    sign = 1;
  835.     if (sscanf(string, scheck(string, "%d"), &hh) == 1)
  836.         mm = ss = 0;
  837.     else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
  838.         ss = 0;
  839.     else if (sscanf(string, scheck(string, "%d:%d:%d"),
  840.         &hh, &mm, &ss) != 3) {
  841.             error(errstring);
  842.             return 0;
  843.     }
  844.     if (hh < 0 || hh >= HOURSPERDAY ||
  845.         mm < 0 || mm >= MINSPERHOUR ||
  846.         ss < 0 || ss > SECSPERMIN) {
  847.             error(errstring);
  848.             return 0;
  849.     }
  850.     return eitol(sign) *
  851.         (eitol(hh * MINSPERHOUR + mm) *
  852.         eitol(SECSPERMIN) + eitol(ss));
  853. }
  854.  
  855. static void
  856. inrule(fields, nfields)
  857. register char ** const    fields;
  858. const int        nfields;
  859. {
  860.     static struct rule    r;
  861.  
  862.     if (nfields != RULE_FIELDS) {
  863.         error("wrong number of fields on Rule line");
  864.         return;
  865.     }
  866.     if (*fields[RF_NAME] == '\0') {
  867.         error("nameless rule");
  868.         return;
  869.     }
  870.     r.r_filename = filename;
  871.     r.r_linenum = linenum;
  872.     r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);
  873.     rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
  874.         fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
  875.     r.r_name = ecpyalloc(fields[RF_NAME]);
  876.     r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
  877.     rules = (struct rule *) erealloc((char *) rules,
  878.         (int) ((nrules + 1) * sizeof *rules));
  879.     rules[nrules++] = r;
  880. }
  881.  
  882. static int
  883. inzone(fields, nfields)
  884. register char ** const    fields;
  885. const int        nfields;
  886. {
  887.     register int    i;
  888.     char        buf[132];
  889.  
  890.     if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
  891.         error("wrong number of fields on Zone line");
  892.         return FALSE;
  893.     }
  894.     if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
  895.         (void) sprintf(buf,
  896.             "\"Zone %s\" line and -l option are mutually exclusive",
  897.             TZDEFAULT);
  898.         error(buf);
  899.         return FALSE;
  900.     }
  901.     if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
  902.         (void) sprintf(buf,
  903.             "\"Zone %s\" line and -p option are mutually exclusive",
  904.             TZDEFRULES);
  905.         error(buf);
  906.         return FALSE;
  907.     }
  908.     for (i = 0; i < nzones; ++i)
  909.         if (zones[i].z_name != NULL &&
  910.             strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
  911.                 (void) sprintf(buf,
  912. "duplicate zone name %s (file \"%s\", line %d)",
  913.                     fields[ZF_NAME],
  914.                     zones[i].z_filename,
  915.                     zones[i].z_linenum);
  916.                 error(buf);
  917.                 return FALSE;
  918.         }
  919.     return inzsub(fields, nfields, FALSE);
  920. }
  921.  
  922. static int
  923. inzcont(fields, nfields)
  924. register char ** const    fields;
  925. const int        nfields;
  926. {
  927.     if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
  928.         error("wrong number of fields on Zone continuation line");
  929.         return FALSE;
  930.     }
  931.     return inzsub(fields, nfields, TRUE);
  932. }
  933.  
  934. static int
  935. inzsub(fields, nfields, iscont)
  936. register char ** const    fields;
  937. const int        nfields;
  938. const int        iscont;
  939. {
  940.     register char *        cp;
  941.     static struct zone    z;
  942.     register int        i_gmtoff, i_rule, i_format;
  943.     register int        i_untilyear, i_untilmonth;
  944.     register int        i_untilday, i_untiltime;
  945.     register int        hasuntil;
  946.  
  947.     if (iscont) {
  948.         i_gmtoff = ZFC_GMTOFF;
  949.         i_rule = ZFC_RULE;
  950.         i_format = ZFC_FORMAT;
  951.         i_untilyear = ZFC_TILYEAR;
  952.         i_untilmonth = ZFC_TILMONTH;
  953.         i_untilday = ZFC_TILDAY;
  954.         i_untiltime = ZFC_TILTIME;
  955.         z.z_name = NULL;
  956.     } else {
  957.         i_gmtoff = ZF_GMTOFF;
  958.         i_rule = ZF_RULE;
  959.         i_format = ZF_FORMAT;
  960.         i_untilyear = ZF_TILYEAR;
  961.         i_untilmonth = ZF_TILMONTH;
  962.         i_untilday = ZF_TILDAY;
  963.         i_untiltime = ZF_TILTIME;
  964.         z.z_name = ecpyalloc(fields[ZF_NAME]);
  965.     }
  966.     z.z_filename = filename;
  967.     z.z_linenum = linenum;
  968.     z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);
  969.     if ((cp = strchr(fields[i_format], '%')) != 0) {
  970.         if (*++cp != 's' || strchr(cp, '%') != 0) {
  971.             error("invalid abbreviation format");
  972.             return FALSE;
  973.         }
  974.     }
  975.     z.z_rule = ecpyalloc(fields[i_rule]);
  976.     z.z_format = ecpyalloc(fields[i_format]);
  977.     hasuntil = nfields > i_untilyear;
  978.     if (hasuntil) {
  979.         z.z_untilrule.r_filename = filename;
  980.         z.z_untilrule.r_linenum = linenum;
  981.         rulesub(&z.z_untilrule,
  982.             fields[i_untilyear],
  983.             "only",
  984.             "",
  985.             (nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan",
  986.             (nfields > i_untilday) ? fields[i_untilday] : "1",
  987.             (nfields > i_untiltime) ? fields[i_untiltime] : "0");
  988.         z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear);
  989.         if (iscont && nzones > 0 && z.z_untiltime < max_time &&
  990.             z.z_untiltime > min_time &&
  991.             zones[nzones - 1].z_untiltime >= z.z_untiltime) {
  992. error("Zone continuation line end time is not after end time of previous line");
  993.             return FALSE;
  994.         }
  995.     }
  996.     zones = (struct zone *) erealloc((char *) zones,
  997.         (int) ((nzones + 1) * sizeof *zones));
  998.     zones[nzones++] = z;
  999.     /*
  1000.     ** If there was an UNTIL field on this line,
  1001.     ** there's more information about the zone on the next line.
  1002.     */
  1003.     return hasuntil;
  1004. }
  1005.  
  1006. static void
  1007. inleap(fields, nfields)
  1008. register char ** const    fields;
  1009. const int        nfields;
  1010. {
  1011.     register const char *        cp;
  1012.     register const struct lookup *    lp;
  1013.     register int            i, j;
  1014.     int                year, month, day;
  1015.     long                dayoff, tod;
  1016.     time_t                t;
  1017.  
  1018.     if (nfields != LEAP_FIELDS) {
  1019.         error("wrong number of fields on Leap line");
  1020.         return;
  1021.     }
  1022.     dayoff = 0;
  1023.     cp = fields[LP_YEAR];
  1024.     if (sscanf((char *)cp, scheck(cp, "%d"), &year) != 1 ||
  1025.         year < min_year || year > max_year) {
  1026.             /*
  1027.              * Leapin' Lizards!
  1028.              */
  1029.             error("invalid leaping year");
  1030.             return;
  1031.     }
  1032.     j = EPOCH_YEAR;
  1033.     while (j != year) {
  1034.         if (year > j) {
  1035.             i = len_years[isleap(j)];
  1036.             ++j;
  1037.         } else {
  1038.             --j;
  1039.             i = -len_years[isleap(j)];
  1040.         }
  1041.         dayoff = oadd(dayoff, eitol(i));
  1042.     }
  1043.     if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
  1044.         error("invalid month name");
  1045.         return;
  1046.     }
  1047.     month = lp->l_value;
  1048.     j = TM_JANUARY;
  1049.     while (j != month) {
  1050.         i = len_months[isleap(year)][j];
  1051.         dayoff = oadd(dayoff, eitol(i));
  1052.         ++j;
  1053.     }
  1054.     cp = fields[LP_DAY];
  1055.     if (sscanf((char *)cp, scheck(cp, "%d"), &day) != 1 ||
  1056.         day <= 0 || day > len_months[isleap(year)][month]) {
  1057.             error("invalid day of month");
  1058.             return;
  1059.     }
  1060.     dayoff = oadd(dayoff, eitol(day - 1));
  1061.     if (dayoff < 0 && !tt_signed) {
  1062.         error("time before zero");
  1063.         return;
  1064.     }
  1065.     t = (time_t) dayoff * SECSPERDAY;
  1066.     /*
  1067.     ** Cheap overflow check.
  1068.     */
  1069.     if (t / SECSPERDAY != dayoff) {
  1070.         error("time overflow");
  1071.         return;
  1072.     }
  1073.     tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);
  1074.     cp = fields[LP_CORR];
  1075.     if (strcmp(cp, "+") != 0 && strcmp(cp, "") != 0) {
  1076.         /* infile() turned "-" into "" */
  1077.         error("illegal CORRECTION field on Leap line");
  1078.         return;
  1079.     }
  1080.     if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
  1081.         error("illegal Rolling/Stationary field on Leap line");
  1082.         return;
  1083.     }
  1084.     addleap(tadd(t, tod), *cp == '+', lp->l_value);
  1085. }
  1086.  
  1087. static void
  1088. inlink(fields, nfields)
  1089. register char ** const    fields;
  1090. const int        nfields;
  1091. {
  1092.     struct link    l;
  1093.  
  1094.     if (nfields != LINK_FIELDS) {
  1095.         error("wrong number of fields on Link line");
  1096.         return;
  1097.     }
  1098.     if (*fields[LF_FROM] == '\0') {
  1099.         error("blank FROM field on Link line");
  1100.         return;
  1101.     }
  1102.     if (*fields[LF_TO] == '\0') {
  1103.         error("blank TO field on Link line");
  1104.         return;
  1105.     }
  1106.     l.l_filename = filename;
  1107.     l.l_linenum = linenum;
  1108.     l.l_from = ecpyalloc(fields[LF_FROM]);
  1109.     l.l_to = ecpyalloc(fields[LF_TO]);
  1110.     links = (struct link *) erealloc((char *) links,
  1111.         (int) ((nlinks + 1) * sizeof *links));
  1112.     links[nlinks++] = l;
  1113. }
  1114.  
  1115. static void
  1116. rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
  1117. register struct rule * const    rp;
  1118. char * const            loyearp;
  1119. char * const            hiyearp;
  1120. char * const            typep;
  1121. char * const            monthp;
  1122. char * const            dayp;
  1123. char * const            timep;
  1124. {
  1125.     register struct lookup const *    lp;
  1126.     register char *            cp;
  1127.  
  1128.     if ((lp = byword(monthp, mon_names)) == NULL) {
  1129.         error("invalid month name");
  1130.         return;
  1131.     }
  1132.     rp->r_month = lp->l_value;
  1133.     rp->r_todisstd = FALSE;
  1134.     cp = timep;
  1135.     if (*cp != '\0') {
  1136.         cp += strlen(cp) - 1;
  1137.         switch (lowerit(*cp)) {
  1138.             case 's':
  1139.                 rp->r_todisstd = TRUE;
  1140.                 *cp = '\0';
  1141.                 break;
  1142.             case 'w':
  1143.                 rp->r_todisstd = FALSE;
  1144.                 *cp = '\0';
  1145.                 break;
  1146.         }
  1147.     }
  1148.     rp->r_tod = gethms(timep, "invalid time of day", FALSE);
  1149.     /*
  1150.     ** Year work.
  1151.     */
  1152.     cp = loyearp;
  1153.     if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {
  1154.         case YR_MINIMUM:
  1155.             rp->r_loyear = min_year;
  1156.             break;
  1157.         case YR_MAXIMUM:
  1158.             rp->r_loyear = max_year;
  1159.             break;
  1160.         default:    /* "cannot happen" */
  1161.             (void) fprintf(stderr,
  1162.                 "%s: panic: Invalid l_value %d\n",
  1163.                 progname, lp->l_value);
  1164.             (void) exit(EXIT_FAILURE);
  1165.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1 ||
  1166.         rp->r_loyear < min_year || rp->r_loyear > max_year) {
  1167.             if (noise)
  1168.                 error("invalid starting year");
  1169.             if (rp->r_loyear > max_year)
  1170.                 return;
  1171.     }
  1172.     cp = hiyearp;
  1173.     if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
  1174.         case YR_MINIMUM:
  1175.             rp->r_hiyear = min_year;
  1176.             break;
  1177.         case YR_MAXIMUM:
  1178.             rp->r_hiyear = max_year;
  1179.             break;
  1180.         case YR_ONLY:
  1181.             rp->r_hiyear = rp->r_loyear;
  1182.             break;
  1183.         default:    /* "cannot happen" */
  1184.             (void) fprintf(stderr,
  1185.                 "%s: panic: Invalid l_value %d\n",
  1186.                 progname, lp->l_value);
  1187.             (void) exit(EXIT_FAILURE);
  1188.     } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1 ||
  1189.         rp->r_hiyear < min_year || rp->r_hiyear > max_year) {
  1190.             if (noise)
  1191.                 error("invalid ending year");
  1192.             if (rp->r_hiyear < min_year)
  1193.                 return;
  1194.     }
  1195.     if (rp->r_hiyear < min_year)
  1196.          return;
  1197.      if (rp->r_loyear < min_year)
  1198.          rp->r_loyear = min_year;
  1199.      if (rp->r_hiyear > max_year)
  1200.          rp->r_hiyear = max_year;
  1201.     if (rp->r_loyear > rp->r_hiyear) {
  1202.         error("starting year greater than ending year");
  1203.         return;
  1204.     }
  1205.     if (*typep == '\0')
  1206.         rp->r_yrtype = NULL;
  1207.     else {
  1208.         if (rp->r_loyear == rp->r_hiyear) {
  1209.             error("typed single year");
  1210.             return;
  1211.         }
  1212.         rp->r_yrtype = ecpyalloc(typep);
  1213.     }
  1214.     /*
  1215.     ** Day work.
  1216.     ** Accept things such as:
  1217.     **    1
  1218.     **    last-Sunday
  1219.     **    Sun<=20
  1220.     **    Sun>=7
  1221.     */
  1222.     if ((lp = byword(dayp, lasts)) != NULL) {
  1223.         rp->r_dycode = DC_DOWLEQ;
  1224.         rp->r_wday = lp->l_value;
  1225.         rp->r_dayofmonth = len_months[1][rp->r_month];
  1226.     } else {
  1227.         if ((cp = strchr(dayp, '<')) != 0)
  1228.             rp->r_dycode = DC_DOWLEQ;
  1229.         else if ((cp = strchr(dayp, '>')) != 0)
  1230.             rp->r_dycode = DC_DOWGEQ;
  1231.         else {
  1232.             cp = dayp;
  1233.             rp->r_dycode = DC_DOM;
  1234.         }
  1235.         if (rp->r_dycode != DC_DOM) {
  1236.             *cp++ = 0;
  1237.             if (*cp++ != '=') {
  1238.                 error("invalid day of month");
  1239.                 return;
  1240.             }
  1241.             if ((lp = byword(dayp, wday_names)) == NULL) {
  1242.                 error("invalid weekday name");
  1243.                 return;
  1244.             }
  1245.             rp->r_wday = lp->l_value;
  1246.         }
  1247.         if (sscanf(cp, scheck(cp, "%d"), &rp->r_dayofmonth) != 1 ||
  1248.             rp->r_dayofmonth <= 0 ||
  1249.             (rp->r_dayofmonth > len_months[1][rp->r_month])) {
  1250.                 error("invalid day of month");
  1251.                 return;
  1252.         }
  1253.     }
  1254. }
  1255.  
  1256. static void
  1257. convert(val, buf)
  1258. const long    val;
  1259. char * const    buf;
  1260. {
  1261.     register int    i;
  1262.     register long    shift;
  1263.  
  1264.     for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
  1265.         buf[i] = val >> shift;
  1266. }
  1267.  
  1268. static void
  1269. puttzcode(val, fp)
  1270. const long    val;
  1271. FILE * const    fp;
  1272. {
  1273.     char    buf[4];
  1274.  
  1275.     convert(val, buf);
  1276.     (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
  1277. }
  1278.  
  1279. static void
  1280. writezone(name)
  1281. const char * const    name;
  1282. {
  1283.     register FILE *        fp;
  1284.     register int        i, j;
  1285.     char            fullname[BUFSIZ];
  1286.     static struct tzhead    tzh;
  1287.  
  1288.     if (strlen(directory) + 1 + strlen(name) >= sizeof fullname) {
  1289.         (void) fprintf(stderr,
  1290.             "%s: File name %s/%s too long\n", progname,
  1291.             directory, name);
  1292.         (void) exit(EXIT_FAILURE);
  1293.     }
  1294.     (void) sprintf(fullname, "%s/%s", directory, name);
  1295.     if ((fp = fopen(fullname, "wb")) == NULL) {
  1296.         if (mkdirs(fullname) != 0)
  1297.             (void) exit(EXIT_FAILURE);
  1298.         if ((fp = fopen(fullname, "wb")) == NULL) {
  1299.             (void) fprintf(stderr, "%s: Can't create ", progname);
  1300.             (void) perror(fullname);
  1301.             (void) exit(EXIT_FAILURE);
  1302.         }
  1303.     }
  1304.     convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
  1305.     convert(eitol(leapcnt), tzh.tzh_leapcnt);
  1306.     convert(eitol(timecnt), tzh.tzh_timecnt);
  1307.     convert(eitol(typecnt), tzh.tzh_typecnt);
  1308.     convert(eitol(charcnt), tzh.tzh_charcnt);
  1309.     (void) fwrite((void *) &tzh, (size_t) sizeof tzh, (size_t) 1, fp);
  1310.     for (i = 0; i < timecnt; ++i) {
  1311.         j = leapcnt;
  1312.         while (--j >= 0)
  1313.             if (ats[i] >= trans[j]) {
  1314.                 ats[i] = tadd(ats[i], corr[j]);
  1315.                 break;
  1316.             }
  1317.         puttzcode((long) ats[i], fp);
  1318.     }
  1319.     if (timecnt > 0)
  1320.         (void) fwrite((void *) types, (size_t) sizeof types[0],
  1321.             (size_t) timecnt, fp);
  1322.     for (i = 0; i < typecnt; ++i) {
  1323.         puttzcode((long) gmtoffs[i], fp);
  1324.         (void) putc(isdsts[i], fp);
  1325.         (void) putc(abbrinds[i], fp);
  1326.     }
  1327.     if (charcnt != 0)
  1328.         (void) fwrite((void *) chars, (size_t) sizeof chars[0],
  1329.             (size_t) charcnt, fp);
  1330.     for (i = 0; i < leapcnt; ++i) {
  1331.         if (roll[i]) {
  1332.             if (timecnt == 0 || trans[i] < ats[0]) {
  1333.                 j = 0;
  1334.                 while (isdsts[j])
  1335.                     if (++j >= typecnt) {
  1336.                         j = 0;
  1337.                         break;
  1338.                     }
  1339.             } else {
  1340.                 j = 1;
  1341.                 while (j < timecnt && trans[i] >= ats[j])
  1342.                     ++j;
  1343.                 j = types[j - 1];
  1344.             }
  1345.             puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
  1346.         } else    puttzcode((long) trans[i], fp);
  1347.         puttzcode((long) corr[i], fp);
  1348.     }
  1349.     for (i = 0; i < typecnt; ++i)
  1350.         (void) putc(ttisstds[i], fp);
  1351.     if (ferror(fp) || fclose(fp)) {
  1352.         (void) fprintf(stderr, "%s: Write error on ", progname);
  1353.         (void) perror(fullname);
  1354.         (void) exit(EXIT_FAILURE);
  1355.     }
  1356. }
  1357.  
  1358. static void
  1359. outzone(zpfirst, zonecount)
  1360. const struct zone * const    zpfirst;
  1361. const int            zonecount;
  1362. {
  1363.     register const struct zone *    zp;
  1364.     register struct rule *        rp;
  1365.     register int            i, j;
  1366.     register int            usestart, useuntil;
  1367.     register time_t            starttime, untiltime;
  1368.     register long            gmtoff;
  1369.     register long            stdoff;
  1370.     register int            year;
  1371.     register long            startoff;
  1372.     register int            startisdst;
  1373.     register int            startttisstd;
  1374.     register int            type;
  1375.     char                startbuf[BUFSIZ];
  1376.  
  1377.     /*
  1378.     ** Now. . .finally. . .generate some useful data!
  1379.     */
  1380.     timecnt = 0;
  1381.     typecnt = 0;
  1382.     charcnt = 0;
  1383.     /*
  1384.     ** Two guesses. . .the second may well be corrected later.
  1385.     */
  1386.     gmtoff = zpfirst->z_gmtoff;
  1387.     stdoff = 0;
  1388. #ifdef lint
  1389.     starttime = 0;
  1390.     startttisstd = FALSE;
  1391. #endif /* defined lint */
  1392.     for (i = 0; i < zonecount; ++i) {
  1393.         usestart = i > 0;
  1394.         useuntil = i < (zonecount - 1);
  1395.         zp = &zpfirst[i];
  1396.         eat(zp->z_filename, zp->z_linenum);
  1397.         startisdst = -1;
  1398.         if (zp->z_nrules == 0) {
  1399.             type = addtype(oadd(zp->z_gmtoff, zp->z_stdoff),
  1400.                 zp->z_format, zp->z_stdoff != 0,
  1401.                 startttisstd);
  1402.             if (usestart)
  1403.                 addtt(starttime, type);
  1404.             gmtoff = zp->z_gmtoff;
  1405.             stdoff = zp->z_stdoff;
  1406.         } else for (year = min_year; year <= max_year; ++year) {
  1407.             if (useuntil && year > zp->z_untilrule.r_hiyear)
  1408.                 break;
  1409.             /*
  1410.             ** Mark which rules to do in the current year.
  1411.             ** For those to do, calculate rpytime(rp, year);
  1412.             */
  1413.             for (j = 0; j < zp->z_nrules; ++j) {
  1414.                 rp = &zp->z_rules[j];
  1415.                 eats(zp->z_filename, zp->z_linenum,
  1416.                     rp->r_filename, rp->r_linenum);
  1417.                 rp->r_todo = year >= rp->r_loyear &&
  1418.                         year <= rp->r_hiyear &&
  1419.                         yearistype(year, rp->r_yrtype);
  1420.                 if (rp->r_todo)
  1421.                     rp->r_temp = rpytime(rp, year);
  1422.             }
  1423.             for ( ; ; ) {
  1424.                 register int    k;
  1425.                 register time_t    jtime, ktime;
  1426.                 register long    offset;
  1427.                 char        buf[BUFSIZ];
  1428.  
  1429.                 if (useuntil) {
  1430.                     /*
  1431.                     ** Turn untiltime into GMT
  1432.                     ** assuming the current gmtoff and
  1433.                     ** stdoff values.
  1434.                     */
  1435.                     offset = gmtoff;
  1436.                     if (!zp->z_untilrule.r_todisstd)
  1437.                         offset = oadd(offset, stdoff);
  1438.                     untiltime = tadd(zp->z_untiltime,
  1439.                         -offset);
  1440.                 }
  1441.                 /*
  1442.                 ** Find the rule (of those to do, if any)
  1443.                 ** that takes effect earliest in the year.
  1444.                 */
  1445.                 k = -1;
  1446. #ifdef lint
  1447.                 ktime = 0;
  1448. #endif /* defined lint */
  1449.                 for (j = 0; j < zp->z_nrules; ++j) {
  1450.                     rp = &zp->z_rules[j];
  1451.                     if (!rp->r_todo)
  1452.                         continue;
  1453.                     eats(zp->z_filename, zp->z_linenum,
  1454.                         rp->r_filename, rp->r_linenum);
  1455.                     offset = gmtoff;
  1456.                     if (!rp->r_todisstd)
  1457.                         offset = oadd(offset, stdoff);
  1458.                     jtime = rp->r_temp;
  1459.                     if (jtime == min_time ||
  1460.                         jtime == max_time)
  1461.                             continue;
  1462.                     jtime = tadd(jtime, -offset);
  1463.                     if (k < 0 || jtime < ktime) {
  1464.                         k = j;
  1465.                         ktime = jtime;
  1466.                     }
  1467.                 }
  1468.                 if (k < 0)
  1469.                     break;    /* go on to next year */
  1470.                 rp = &zp->z_rules[k];
  1471.                 rp->r_todo = FALSE;
  1472.                 if (useuntil && ktime >= untiltime)
  1473.                     break;
  1474.                 if (usestart) {
  1475.                     if (ktime < starttime) {
  1476.                         stdoff = rp->r_stdoff;
  1477.                         startoff = oadd(zp->z_gmtoff,
  1478.                             rp->r_stdoff);
  1479.                         (void) sprintf(startbuf,
  1480.                             zp->z_format,
  1481.                             rp->r_abbrvar);
  1482.                         startisdst =
  1483.                             rp->r_stdoff != 0;
  1484.                         continue;
  1485.                     }
  1486.                     if (ktime != starttime &&
  1487.                         startisdst >= 0)
  1488. addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
  1489.                     usestart = FALSE;
  1490.                 }
  1491.                 eats(zp->z_filename, zp->z_linenum,
  1492.                     rp->r_filename, rp->r_linenum);
  1493.                 (void) sprintf(buf, zp->z_format,
  1494.                     rp->r_abbrvar);
  1495.                 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
  1496.                 type = addtype(offset, buf, rp->r_stdoff != 0,
  1497.                     rp->r_todisstd);
  1498.                 if (timecnt != 0 || rp->r_stdoff != 0)
  1499.                     addtt(ktime, type);
  1500.                 gmtoff = zp->z_gmtoff;
  1501.                 stdoff = rp->r_stdoff;
  1502.             }
  1503.         }
  1504.         /*
  1505.         ** Now we may get to set starttime for the next zone line.
  1506.         */
  1507.         if (useuntil) {
  1508.             starttime = tadd(zp->z_untiltime,
  1509.                 -gmtoffs[types[timecnt - 1]]);
  1510.             startttisstd = zp->z_untilrule.r_todisstd;
  1511.         }
  1512.     }
  1513.     writezone(zpfirst->z_name);
  1514. }
  1515.  
  1516. static void
  1517. addtt(starttime, type)
  1518. const time_t    starttime;
  1519. const int    type;
  1520. {
  1521.     if (timecnt != 0 && type == types[timecnt - 1])
  1522.         return;    /* easy enough! */
  1523.     if (timecnt >= TZ_MAX_TIMES) {
  1524.         error("too many transitions?!");
  1525.         (void) exit(EXIT_FAILURE);
  1526.     }
  1527.     ats[timecnt] = starttime;
  1528.     types[timecnt] = type;
  1529.     ++timecnt;
  1530. }
  1531.  
  1532. static int
  1533. addtype(gmtoff, abbr, isdst, ttisstd)
  1534. const long        gmtoff;
  1535. const char * const    abbr;
  1536. const int        isdst;
  1537. const int        ttisstd;
  1538. {
  1539.     register int    i, j;
  1540.  
  1541.     /*
  1542.     ** See if there's already an entry for this zone type.
  1543.     ** If so, just return its index.
  1544.     */
  1545.     for (i = 0; i < typecnt; ++i) {
  1546.         if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
  1547.             strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
  1548.             ttisstd == ttisstds[i])
  1549.                 return i;
  1550.     }
  1551.     /*
  1552.     ** There isn't one; add a new one, unless there are already too
  1553.     ** many.
  1554.     */
  1555.     if (typecnt >= TZ_MAX_TYPES) {
  1556.         error("too many local time types");
  1557.         (void) exit(EXIT_FAILURE);
  1558.     }
  1559.     gmtoffs[i] = gmtoff;
  1560.     isdsts[i] = isdst;
  1561.     ttisstds[i] = ttisstd;
  1562.  
  1563.     for (j = 0; j < charcnt; ++j)
  1564.         if (strcmp(&chars[j], abbr) == 0)
  1565.             break;
  1566.     if (j == charcnt)
  1567.         newabbr(abbr);
  1568.     abbrinds[i] = j;
  1569.     ++typecnt;
  1570.     return i;
  1571. }
  1572.  
  1573. static void
  1574. addleap(t, positive, rolling)
  1575. const time_t    t;
  1576. const int    positive;
  1577. const int    rolling;
  1578. {
  1579.     register int    i, j;
  1580.  
  1581.     if (leapcnt >= TZ_MAX_LEAPS) {
  1582.         error("too many leap seconds");
  1583.         (void) exit(EXIT_FAILURE);
  1584.     }
  1585.     for (i = 0; i < leapcnt; ++i)
  1586.         if (t <= trans[i]) {
  1587.             if (t == trans[i]) {
  1588.                 error("repeated leap second moment");
  1589.                 (void) exit(EXIT_FAILURE);
  1590.             }
  1591.             break;
  1592.         }
  1593.     for (j = leapcnt; j > i; --j) {
  1594.         trans[j] = trans[j-1];
  1595.         corr[j] = corr[j-1];
  1596.         roll[j] = roll[j-1];
  1597.     }
  1598.     trans[i] = t;
  1599.     corr[i] = (positive ? 1L : -1L);
  1600.     roll[i] = rolling;
  1601.     ++leapcnt;
  1602. }
  1603.  
  1604. static void
  1605. adjleap()
  1606. {
  1607.     register int    i;
  1608.     register long    last = 0;
  1609.  
  1610.     /*
  1611.     ** propagate leap seconds forward
  1612.     */
  1613.     for (i = 0; i < leapcnt; ++i) {
  1614.         trans[i] = tadd(trans[i], last);
  1615.         last = corr[i] += last;
  1616.     }
  1617. }
  1618.  
  1619. static int
  1620. yearistype(year, type)
  1621. const int        year;
  1622. const char * const    type;
  1623. {
  1624.     char    buf[BUFSIZ];
  1625.     int    result;
  1626.  
  1627.     if (type == NULL || *type == '\0')
  1628.         return TRUE;
  1629.     if (strcmp(type, "uspres") == 0)
  1630.         return (year % 4) == 0;
  1631.     if (strcmp(type, "nonpres") == 0)
  1632.         return (year % 4) != 0;
  1633.     (void) sprintf(buf, "yearistype %d %s", year, type);
  1634.     result = system(buf);
  1635.     if (result == 0)
  1636.         return TRUE;
  1637.     if (result == (1 << 8))
  1638.         return FALSE;
  1639.     error("Wild result from command execution");
  1640.     (void) fprintf(stderr, "%s: command was '%s', result was %d\n",
  1641.         progname, buf, result);
  1642.     for ( ; ; )
  1643.         (void) exit(EXIT_FAILURE);
  1644. }
  1645.  
  1646. static int
  1647. lowerit(a)
  1648. const int    a;
  1649. {
  1650.     return (isascii(a) && isupper(a)) ? tolower(a) : a;
  1651. }
  1652.  
  1653. static int
  1654. ciequal(ap, bp)        /* case-insensitive equality */
  1655. register const char *    ap;
  1656. register const char *    bp;
  1657. {
  1658.     while (lowerit(*ap) == lowerit(*bp++))
  1659.         if (*ap++ == '\0')
  1660.             return TRUE;
  1661.     return FALSE;
  1662. }
  1663.  
  1664. static int
  1665. itsabbr(abbr, word)
  1666. register const char *    abbr;
  1667. register const char *    word;
  1668. {
  1669.     if (lowerit(*abbr) != lowerit(*word))
  1670.         return FALSE;
  1671.     ++word;
  1672.     while (*++abbr != '\0')
  1673.         do if (*word == '\0')
  1674.             return FALSE;
  1675.                 while (lowerit(*word++) != lowerit(*abbr));
  1676.     return TRUE;
  1677. }
  1678.  
  1679. static const struct lookup *
  1680. byword(word, table)
  1681. register const char * const        word;
  1682. register const struct lookup * const    table;
  1683. {
  1684.     register const struct lookup *    foundlp;
  1685.     register const struct lookup *    lp;
  1686.  
  1687.     if (word == NULL || table == NULL)
  1688.         return NULL;
  1689.     /*
  1690.     ** Look for exact match.
  1691.     */
  1692.     for (lp = table; lp->l_word != NULL; ++lp)
  1693.         if (ciequal(word, lp->l_word))
  1694.             return lp;
  1695.     /*
  1696.     ** Look for inexact match.
  1697.     */
  1698.     foundlp = NULL;
  1699.     for (lp = table; lp->l_word != NULL; ++lp)
  1700.         if (itsabbr(word, lp->l_word))
  1701.             if (foundlp == NULL)
  1702.                 foundlp = lp;
  1703.             else    return NULL;    /* multiple inexact matches */
  1704.     return foundlp;
  1705. }
  1706.  
  1707. static char **
  1708. getfields(cp)
  1709. register char *    cp;
  1710. {
  1711.     register char *        dp;
  1712.     register char **    array;
  1713.     register int        nsubs;
  1714.  
  1715.     if (cp == NULL)
  1716.         return NULL;
  1717.     array = (char **) emalloc((int) ((strlen(cp) + 1) * sizeof *array));
  1718.     nsubs = 0;
  1719.     for ( ; ; ) {
  1720.         while (isascii(*cp) && isspace(*cp))
  1721.             ++cp;
  1722.         if (*cp == '\0' || *cp == '#')
  1723.             break;
  1724.         array[nsubs++] = dp = cp;
  1725.         do {
  1726.             if ((*dp = *cp++) != '"')
  1727.                 ++dp;
  1728.             else while ((*dp = *cp++) != '"')
  1729.                 if (*dp != '\0')
  1730.                     ++dp;
  1731.                 else    error("Odd number of quotation marks");
  1732.         } while (*cp != '\0' && *cp != '#' &&
  1733.             (!isascii(*cp) || !isspace(*cp)));
  1734.         if (isascii(*cp) && isspace(*cp))
  1735.             ++cp;
  1736.         *dp = '\0';
  1737.     }
  1738.     array[nsubs] = NULL;
  1739.     return array;
  1740. }
  1741.  
  1742. static long
  1743. oadd(t1, t2)
  1744. const long    t1;
  1745. const long    t2;
  1746. {
  1747.     register long    t;
  1748.  
  1749.     t = t1 + t2;
  1750.     if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) {
  1751.         error("time overflow");
  1752.         (void) exit(EXIT_FAILURE);
  1753.     }
  1754.     return t;
  1755. }
  1756.  
  1757. static time_t
  1758. tadd(t1, t2)
  1759. const time_t    t1;
  1760. const long    t2;
  1761. {
  1762.     register time_t    t;
  1763.  
  1764.     if (t1 == max_time && t2 > 0)
  1765.         return max_time;
  1766.     if (t1 == min_time && t2 < 0)
  1767.         return min_time;
  1768.     t = t1 + t2;
  1769.     if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) {
  1770.         error("time overflow");
  1771.         (void) exit(EXIT_FAILURE);
  1772.     }
  1773.     return t;
  1774. }
  1775.  
  1776. /*
  1777. ** Given a rule, and a year, compute the date - in seconds since January 1,
  1778. ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
  1779. */
  1780.  
  1781. static time_t
  1782. rpytime(rp, wantedy)
  1783. register const struct rule * const    rp;
  1784. register const int            wantedy;
  1785. {
  1786.     register int    y, m, i;
  1787.     register long    dayoff;            /* with a nod to Margaret O. */
  1788.     register time_t    t;
  1789.  
  1790.     dayoff = 0;
  1791.     m = TM_JANUARY;
  1792.     y = EPOCH_YEAR;
  1793.     while (wantedy != y) {
  1794.         if (wantedy > y) {
  1795.             i = len_years[isleap(y)];
  1796.             ++y;
  1797.         } else {
  1798.             --y;
  1799.             i = -len_years[isleap(y)];
  1800.         }
  1801.         dayoff = oadd(dayoff, eitol(i));
  1802.     }
  1803.     while (m != rp->r_month) {
  1804.         i = len_months[isleap(y)][m];
  1805.         dayoff = oadd(dayoff, eitol(i));
  1806.         ++m;
  1807.     }
  1808.     i = rp->r_dayofmonth;
  1809.     if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
  1810.         if (rp->r_dycode == DC_DOWLEQ)
  1811.             --i;
  1812.         else {
  1813.             error("use of 2/29 in non leap-year");
  1814.             (void) exit(EXIT_FAILURE);
  1815.         }
  1816.     }
  1817.     --i;
  1818.     dayoff = oadd(dayoff, eitol(i));
  1819.     if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
  1820.         register long    wday;
  1821.  
  1822. #define LDAYSPERWEEK    ((long) DAYSPERWEEK)
  1823.         wday = eitol(EPOCH_WDAY);
  1824.         /*
  1825.         ** Don't trust mod of negative numbers.
  1826.         */
  1827.         if (dayoff >= 0)
  1828.             wday = (wday + dayoff) % LDAYSPERWEEK;
  1829.         else {
  1830.             wday -= ((-dayoff) % LDAYSPERWEEK);
  1831.             if (wday < 0)
  1832.                 wday += LDAYSPERWEEK;
  1833.         }
  1834.         while (wday != eitol(rp->r_wday))
  1835.             if (rp->r_dycode == DC_DOWGEQ) {
  1836.                 dayoff = oadd(dayoff, (long) 1);
  1837.                 if (++wday >= LDAYSPERWEEK)
  1838.                     wday = 0;
  1839.                 ++i;
  1840.             } else {
  1841.                 dayoff = oadd(dayoff, (long) -1);
  1842.                 if (--wday < 0)
  1843.                     wday = LDAYSPERWEEK;
  1844.                 --i;
  1845.             }
  1846.         if (i < 0 || i >= len_months[isleap(y)][m]) {
  1847.             error("no day in month matches rule");
  1848.             (void) exit(EXIT_FAILURE);
  1849.         }
  1850.     }
  1851.     if (dayoff < 0 && !tt_signed) {
  1852.         if (wantedy == rp->r_loyear)
  1853.             return min_time;
  1854.         error("time before zero");
  1855.         (void) exit(EXIT_FAILURE);
  1856.     }
  1857.     t = (time_t) dayoff * SECSPERDAY;
  1858.     /*
  1859.     ** Cheap overflow check.
  1860.     */
  1861.     if (t / SECSPERDAY != dayoff) {
  1862.         if (wantedy == rp->r_hiyear)
  1863.             return max_time;
  1864.         if (wantedy == rp->r_loyear)
  1865.             return min_time;
  1866.         error("time overflow");
  1867.         (void) exit(EXIT_FAILURE);
  1868.     }
  1869.     return tadd(t, rp->r_tod);
  1870. }
  1871.  
  1872. static void
  1873. newabbr(string)
  1874. const char * const    string;
  1875. {
  1876.     register int    i;
  1877.  
  1878.     i = strlen(string) + 1;
  1879.     if (charcnt + i >= TZ_MAX_CHARS) {
  1880.         error("too many, or too long, time zone abbreviations");
  1881.         (void) exit(EXIT_FAILURE);
  1882.     }
  1883.     (void) strcpy(&chars[charcnt], string);
  1884.     charcnt += eitol(i);
  1885. }
  1886.  
  1887. static int
  1888. mkdirs(name)
  1889. char * const    name;
  1890. {
  1891.     register char *    cp;
  1892.  
  1893.     if ((cp = name) == NULL || *cp == '\0')
  1894.         return 0;
  1895.     while ((cp = strchr(cp + 1, '/')) != 0) {
  1896.         *cp = '\0';
  1897.         if (!itsdir(name)) {
  1898.             /*
  1899.             ** It doesn't seem to exist, so we try to create it.
  1900.             */
  1901.             if (mkdir(name, 0755) != 0) {
  1902.                 (void) fprintf(stderr,
  1903.                     "%s: Can't create directory ",
  1904.                     progname);
  1905.                 (void) perror(name);
  1906.                 return -1;
  1907.             }
  1908.         }
  1909.         *cp = '/';
  1910.     }
  1911.     return 0;
  1912. }
  1913.  
  1914. static long
  1915. eitol(i)
  1916. const int    i;
  1917. {
  1918.     long    l;
  1919.  
  1920.     l = i;
  1921.     if (i < 0 && l >= 0 || i == 0 && l != 0 || i > 0 && l <= 0) {
  1922.         (void) fprintf(stderr, "%s: %d did not sign extend correctly\n",
  1923.             progname, i);
  1924.         (void) exit(EXIT_FAILURE);
  1925.     }
  1926.     return l;
  1927. }
  1928.  
  1929. /*
  1930. ** UNIX is a registered trademark of AT&T.
  1931. */
  1932.